import java.util.Properties;

import javax.activation.DataHandler;
import javax.activation.DataSource;
import javax.activation.FileDataSource;
import javax.mail.Address;
import javax.mail.FetchProfile;
import javax.mail.Flags;
import javax.mail.Flags.Flag;
import javax.mail.Folder;
import javax.mail.Message;
import javax.mail.MessagingException;
import javax.mail.Multipart;
import javax.mail.PasswordAuthentication;
import javax.mail.Session;
import javax.mail.Store;
import javax.mail.Transport;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeBodyPart;
import javax.mail.internet.MimeMessage;
import javax.mail.internet.MimeMultipart;
import javax.mail.search.FlagTerm;
import javax.swing.JOptionPane;

/*
 * Mail.java - This class uses external jar which is javax.jar to connect the program to the Gmail. 
 * 				To send, re-ceive e-mails from the program input and output door is the Mail class.
 * 
 * @Author : BilCIS
 */

public class Mail 
{
	// Variables declaration
	private String username;
    private String password;
    private String mes;
    private String subject;
    private	String 	path;
    private	String 	name;
    
    private Folder inbox;
    
    private int		numOfMessages;
    
    private	Message[] 		messages;
    
    private	boolean flag;
    // End of variables declaration
    
    public Mail ()
    {
    	username = "";
    	password = "";
    	mes = "";
    	subject = "";
    	flag = false;
    }
    
    public Mail ( String username, String password )
    {
    	this.username = username;
    	this.password = password;
    	mes = "";
    	subject = "";
    	flag = false;
    }
    
    // sets subject
    public void setSubject( String subject )
    {
    	this.subject = subject;
    }
    
    // adds attachment
    public void setAttachment( String path, String name )
    {
    	this.path = path;
    	this.name = name;
    	flag = true;
    }
    
    // sets message
    public void setMessage( String mes )
    {
    	this.mes = mes;
    }
    
    // sets getSpecificMessage
    public String getSpecificMessage ( int num )
    {
    	return messages[num-1].toString();
    }
    
    // reads the mail
    public void readMail()
    {
	   	 Properties props = System.getProperties();
	   	 props.setProperty("mail.store.protocol", "imaps");
	   	 try
	   	 {
	   		/*  Create the session and get the store for read the mail. */
			 Session session = Session.getDefaultInstance(props, null);
			 Store store = session.getStore("imaps");
			 store.connect("imap.gmail.com", username, password);
			 
			 /*  Mention the folder name which you want to read. */
			 inbox = store.getFolder("Inbox");
			 numOfMessages = inbox.getUnreadMessageCount();
			 
			 /*Open the inbox using store.*/
			 inbox.open(Folder.READ_ONLY);
			 
			 /*  Get the messages which is unread in the Inbox*/
			 messages = inbox.search(new FlagTerm(new Flags(Flag.SEEN), false));
			 
			 /* Use a suitable FetchProfile    */
			 FetchProfile fp = new FetchProfile();
			 fp.add(FetchProfile.Item.ENVELOPE);
			 fp.add(FetchProfile.Item.CONTENT_INFO);
			 inbox.fetch(messages, fp);
			 
			 try
			 {
				 inbox.close(true);
				 store.close();
			 }
			 catch (Exception ex)
			 {
				 JOptionPane.showMessageDialog(null, "Exception arise at the time of read mail" );
				 ex.printStackTrace();
			 }
	   	 }
		 catch (MessagingException e)
		 {
			 e.printStackTrace();
		 }

    }
    
    // prints the messages
    public void printAllMessages() throws Exception
    {
    	readMail();
	    for (int i = 0; i < messages.length; i++)
	    {
		    System.out.println("MESSAGE #" + (i + 1) + ":");
		    printEnvelope(messages[i]);
	    }
    }
    
    // gets the mail with given index
    public String getMail ( int specificMes) throws Exception
    {
    	readMail();
	    String str;
	    
	    Address[] a = messages[specificMes].getFrom();
	    
	    String to = a[0].toString();
	    if ( to.indexOf("<") == -1)
	    	str = "FROM: " + to;
	    else
	    	str = to.substring(a[0].toString().indexOf("<"));
	    
	    // SUBJECT
	    str +=  "\nSubject: " + messages[specificMes].getSubject();
	    // Date
	    str += "\nReceived Date : " + messages[specificMes].getReceivedDate().toString().substring(0,
	    													messages[specificMes].getReceivedDate().toString().indexOf("EEST 2013"));
	    
	    return str;
    }
    
    
    /*  Print the envelope(FromAddress,ReceivedDate,Subject)  */
    public void printEnvelope(Message message) throws Exception
    {
	    Address[] a;
	    // FROM
	    if ((a = message.getFrom()) != null)
	    {
		    for (int j = 0; j < a.length; j++)
		    {
		    	System.out.println("FROM: " + a[j].toString());
		    }
	    }
	    
	    // TO
	    if ((a = message.getRecipients(Message.RecipientType.TO)) != null)
		{
		    for (int j = 0; j < a.length; j++)
		    {
		    	System.out.println("TO: " + a[j].toString());
		    }
	    }
	    
	    String subject = message.getSubject();
	    java.util.Date receivedDate = message.getReceivedDate();
	    System.out.println("Subject : " + subject);
	    System.out.println("Received Date : " + receivedDate.toString());
    }
    
    // gets unread message
    public int getUnreadMessage()
    {
    	readMail();
    	return numOfMessages;
    }
    
    // sends the message
    public void send( String senderMail )
    {
	   	Properties props = new Properties();
	    props.put("mail.smtp.starttls.enable", "true");
	  	props.put("mail.smtp.auth", "true");
	  	props.put("mail.smtp.host", "smtp.gmail.com");
	  	props.put("mail.smtp.port", "587");
	  	
    	Session session = Session.getInstance(props, new javax.mail.Authenticator() {
    		protected PasswordAuthentication getPasswordAuthentication() {
    			return new PasswordAuthentication(username, password);
    			}
    		});
    	
    	Multipart multipart = null;
    	if ( flag == true )
    	{
        	MimeBodyPart messageBodyPart = new MimeBodyPart();
        	multipart = new MimeMultipart(); 
        	
        	DataSource source =   new FileDataSource(path);
        	
        	try {
    			messageBodyPart.setDataHandler( new DataHandler(source));
    			messageBodyPart.setFileName(name);
    			multipart.addBodyPart(messageBodyPart);
    		} catch (MessagingException e1) {
    			e1.printStackTrace();
    		} 
    	}

    	try 
    	{
	    	Message message = new MimeMessage(session);
	    	message.setFrom(new InternetAddress( username ));
	    	message.setRecipients(Message.RecipientType.TO,
	    			InternetAddress.parse( senderMail ));
	    	message.setSubject( subject);
	    	message.setText( mes );
	    	if ( flag == true )
	    		message.setContent(multipart);  
	    	
	    	Transport.send(message);      
	    	JOptionPane.showMessageDialog(null, "Message has sent" );

    	} 
    	catch (MessagingException e) 
    	{
    		JOptionPane.showMessageDialog(null, e.getMessage() );
    	} 
    }    
}